{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# ipyvolume: 3D plotting in the notebook\n",
    "\n",
    "## https://github.com/maartenbreddels/ipyvolume\n",
    "\n",
    "IPyvolume is a Python library to visualize 3d volumes and glyphs (e.g. 3d scatter plots), in the Jupyter notebook, with minimal configuration and effort. It is currently pre-1.0, so use at own risk. IPyvolume’s volshow is to 3d arrays what matplotlib’s imshow is to 2d arrays.\n",
    "\n",
    "- MIT Licensed\n",
    "\n",
    "By Maarten Breddels\n",
    "\n",
    "**Installation:**\n",
    "\n",
    "```bash\n",
    "conda install -c conda-forge ipyvolume\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3-D Scatter Plots"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import ipyvolume as ipv\n",
    "import numpy as np\n",
    "import ipywidgets as widgets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x, y, z = np.random.random((3, 10000))\n",
    "ipv.figure()\n",
    "scatter = ipv.scatter(x, y, z, size=1, marker=\"sphere\")\n",
    "ipv.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ipv.save('standalone.html')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!open standalone.html"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x, y, z, u, v, w = np.random.random((6, 1000))*2-1\n",
    "selected = np.random.randint(0, 1000, 100)\n",
    "fig = ipv.figure()\n",
    "quiver = ipv.quiver(x, y, z, u, v, w, size=5, size_selected=8, selected=selected)\n",
    "ipv.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "size = widgets.FloatSlider(min=0, max=30, step=0.1)\n",
    "size_selected = widgets.FloatSlider(min=0, max=30, step=0.1)\n",
    "color = widgets.ColorPicker()\n",
    "color_selected = widgets.ColorPicker()\n",
    "widgets.jslink((quiver, 'size'), (size, 'value'))\n",
    "widgets.jslink((quiver, 'size_selected'), (size_selected, 'value'))\n",
    "widgets.jslink((quiver, 'color'), (color, 'value'))\n",
    "widgets.jslink((quiver, 'color_selected'), (color_selected, 'value'))\n",
    "widgets.VBox([size, size_selected, color, color_selected])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Animations"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# create 2d grids: x, y, and r\n",
    "u = np.linspace(-10, 10, 25)\n",
    "x, y = np.meshgrid(u, u)\n",
    "r = np.sqrt(x**2+y**2)\n",
    "print(\"x,y and z are of shape\", x.shape)\n",
    "# and turn them into 1d\n",
    "x = x.flatten()\n",
    "y = y.flatten()\n",
    "r = r.flatten()\n",
    "print(\"and flattened of shape\", x.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# create a sequence of 15 time elements\n",
    "time = np.linspace(0, np.pi*2, 15)\n",
    "z = np.array([(np.cos(r + t) * np.exp(-r/5)) for t in time])\n",
    "print(\"z is of shape\", z.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# draw the scatter plot, and add controls with animate_glyphs\n",
    "ipv.figure()\n",
    "s = ipv.scatter(x, z, y, marker=\"sphere\")\n",
    "ipv.animation_control(s, interval=200)\n",
    "ipv.ylim(-3,3)\n",
    "ipv.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Now also include, color, which containts rgb values\n",
    "color = np.array([[np.cos(r + t), 1-np.abs(z[i]), 0.1+z[i]*0] for i, t in enumerate(time)])\n",
    "size = (z+1)\n",
    "print(\"color is of shape\", color.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "color = np.transpose(color, (0, 2, 1)) # flip the last axes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ipv.figure()\n",
    "s = ipv.scatter(x, z, y, color=color, size=size, marker=\"sphere\")\n",
    "ipv.animation_control(s, interval=200)\n",
    "ipv.ylim(-3, 3)\n",
    "ipv.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "widgets-tutorial",
   "language": "python",
   "name": "widgets-tutorial"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
